#include "StdAfx.h"
#include "CSGDifference.h"


CCSGDifference::CCSGDifference(void)
{
}


CCSGDifference::~CCSGDifference(void)
{
}

bool CCSGDifference::IsIntersect(const CRay& vRay, DATA_TYPE& t, bool& bInside, CVector3D& vNormal) const
{
	vector<IntersectionPoint> vIntersections;
	GetAllIntersectionPoints(vRay, vIntersections);

	if (vIntersections.empty())
	{
		return false;
	}

	const IntersectionPoint& vFirstPt = *min_element(vIntersections.begin(), vIntersections.end(), IntersectionPointComp);

	t = vFirstPt.t;
	bInside = vFirstPt.isInside;
	vNormal = vFirstPt.vNormal;
	return true;
}

bool CCSGDifference::IsInGeometry(const CVector3D& vPoint) const
{
	return m_spLeft->IsInGeometry(vPoint) && !m_spRight->IsInGeometry(vPoint);
}

bool CCSGDifference::GetAllIntersectionPoints(const CRay& vRay, vector<IntersectionPoint>& vIntersectionPoints) const
{
	vector<IntersectionPoint> vLeftIntersectionPts;
	vector<IntersectionPoint> vRightIntersectionPts;

	m_spLeft->GetAllIntersectionPoints(vRay, vLeftIntersectionPts);
	m_spRight->GetAllIntersectionPoints(vRay, vRightIntersectionPts);

	for (vector<IntersectionPoint>::const_iterator it = vLeftIntersectionPts.begin(); 
		it != vLeftIntersectionPts.end(); ++it)
	{
		const IntersectionPoint& ip = *it;

		CVector3D vPoint = vRay.GetOrigin() + ip.t * vRay.GetDir();
		if (m_spRight->IsInGeometry(vPoint) == false)
		{
			vIntersectionPoints.push_back(ip);
		}
	}

	for (vector<IntersectionPoint>::const_iterator it = vRightIntersectionPts.begin(); 
		it != vRightIntersectionPts.end(); ++it)
	{
		const IntersectionPoint& ip = *it;

		CVector3D vPoint = vRay.GetOrigin() + ip.t * vRay.GetDir();
		if (m_spLeft->IsInGeometry(vPoint) == true)
		{
			vIntersectionPoints.push_back(IntersectionPoint(ip.t, !ip.isInside, -ip.vNormal));
		}
	}

	return !vIntersectionPoints.empty();
}